/**
 * \file   ts.h
 * \author Fabian Jesus Machado
 * \date   Septiembre de 2011
 * 
 *  Este archivo es parte del proyecto NPASM, un ensamblador para
 * microcontroladores PIC con sintaxis Intel, desarrollado inicialmente
 * por Fabian Machado (fabianjsm@gmail.com, twitter@fabianjsm).
 *  El codigo fuente esta diponible en el repositorio SVN de Google:
 *      http://npasm.googlecode.com/svn/trunk.
 * 
 * 
 */
#ifndef TS_H
#define TS_H
#include <iostream>
#include <list>
#include "simbolo.h"

class ts;

/**
 * Tipo que declara una lista de tablas.
 */
typedef std::list<ts, std::allocator<ts> > ts_list_t;

/**
 * Tipo iterador que permite recorrer la lista de tablas.
 */
typedef std::list<ts, std::allocator<ts> >::iterator ts_list_iterator_t;

/**
 * Tabla de simbolos.
 */
class ts {
public:
	/**
	 * Construye una tabla raiz (padre de si misma) con el \a nombre
	 * especificado.
	 */
	ts(std::string _nombre="");

	/**
	 * Propiedad que devuelve el \a nombre de la tabla.
	 */
	std::string GetNombre();

	/**
	 *  Busca un simbolo publico con el \a nombre especificado, devuelve
	 * cero o un puntero valido.
	 */
	simbolo *Buscar(std::string _nombre);

	/**
	 *  Busca un simbolo local con el \a nombre especificado, devuelve
	 * cero o un puntero valido.
	 */
	simbolo *BuscarLocal(std::string _nombre);

	/**
	 *Busca el simbolo con el \a nombre especificado en el ambito local.
	 * \return Retorna un puntero valido o cero si no lo encuentra.
	 */
	simbolo *SimboloLocal(std::string _nombre);

	/**
	 *  Busca el simbolo con el \a nombre especificado, tanto en el
	 * ambito publico como el local. Si no lo encuetra lo crea en el
	 * ambito local.
	 * \return Retorna un puntero valido o cero si falla.
	 */
	simbolo *Simbolo(std::string _nombre);

	/**
	 *  Elimina el simbolo local con el \a nombre especificado y retorna
	 * true. Si no lo encuentra retorna false.
	 */
	bool Eliminar(std::string _nombre);

	/**
	 *Propiedad que devuelve la cantidad de simbolos que posee la tabla.
	 */
	int GetCount();

	/**
	 * Propiedad que devuelve el puntero al padre de la tabla.
	 */
	ts *GetPadre();

	/**
	 *  Crea un simbolo local con el \a nombre espcificado. Si ya existe
	 * un simbolo local con el nombre, retorna cero, en otro caso
	 * retorna un puntero valido al simbolo creado.
	 */
	simbolo *Insertar(std::string _nombre);

	/**
	 *  Busca una tabla hija con el \a nombre especificado. Si la
	 * encuentra retorna un puntero valido a ella, en otro caso retorna
	 * cero.
	 */
	ts *BuscarTabla(std::string _nombre);

	/**
	 * Crea una tabla con el \a nombre especificado y retorna un puntero
	 * valido a ella. Retorna cero si falla.
	 */
	ts *NuevaTabla(std::string _nombre);

	/**
	 *  Busca localmente una tabla con el \a nombre especificado, si no
	 * la encuentra la crea. Retorna un puntero valido a la tabla creada
	 * o encontrada, o cero si falla.
	 */
	ts *Tabla(std::string _nombre);

	/**
	 * Iterador al inicio de la lista de simbolos.
	 */
	sblspace::sbl_list_iterator_t GetSblInicio_iterator();

	/**
	 * Iterador al final de la lista de simbolos.
	 */
	sblspace::sbl_list_iterator_t GetSblFin_iterator();

	/**
	 * Iterador al inicio de la lista de tablas.
	 */
	ts_list_iterator_t GetTsInicio_iterator();

	/**
	 * Iterador al final de la lista de tablas.
	 */
	ts_list_iterator_t GetTsFin_iterator();

	/**
	 *  Operador empleado para comparar tablas. Se considera que dos
	 * tablas son iguales cuando poseen igual \a nombre. Se necesita
	 * para buscar tablas empleando el algoritmo 'find' de la STL.
	 */
	bool operator==(std::string _nombre);

private:
	/**
	 *  Cronstruye una tabla hija de la tabla _padre con el \a nombre
	 * espcificado.
	 */
	ts(std::string _nombre, ts *_padre);

	/**
	 * Crea un simbolo local con el \a nombre especificado.
	 */
	simbolo *insertarLocal(std::string _nombre);

	/**
	 * Nombre de la tabla
	 */
	std::string nombre;

	/**
	 * Puntero al padre de la tabla
	 */
	ts *padre;

	/**
	 * Lista de simbolos
	 */
	sblspace::sbl_list_t lista;

	/**
	 * Lista de tablas
	 */
	ts_list_t hijo;
};

#endif // TS_H
